﻿using System;
using System.Xml.XPath;
using System.Configuration;
using System.Collections;
using System.Text;
using System.IO;

namespace GaiNo.Core.Data
{
    internal class SqlMapBuilder
    {
        private const string _INSERT = "insert into ";
        private const string _UPDATE = "update ";
        private const string _DELETE = "delete from ";
        private const string _SELECT = "select * from ";
        private const string _WHERE = " where ";
        private const string _SET = " set ";

        private Hashtable _maps = new Hashtable();        
        public ISqlMapper ConfigureAndWatch()
        {
            configure();
            return new SqlMapper(_maps);
        }
        
        private void configure()
        {
            StringBuilder strSqlInsert = null;
            StringBuilder strSqlUpdate = null;
            StringBuilder strSqlDelete = null;
            StringBuilder strSqlSelect = null;
            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config\\sqlmap.config");
            XPathDocument doc = new XPathDocument(path);
            string navigator = "/sqlMaps/map";
            XPathNavigator nav = doc.CreateNavigator();

            XPathNodeIterator iter = nav.Select(navigator);
            string tableName = string.Empty;
            string insert = string.Empty;
            bool identity = false;
            string classFullName = string.Empty;
            while (iter.MoveNext())
            {
                if (iter.Current.HasAttributes)
                {
                    strSqlInsert = new StringBuilder(_INSERT);
                    strSqlDelete = new StringBuilder(_DELETE);
                    strSqlSelect = new StringBuilder(_SELECT);
                    strSqlUpdate = new StringBuilder(_UPDATE);
                    tableName = iter.Current.GetAttribute("name", "");
                    identity = iter.Current.GetAttribute("identity", "").ToLower().Equals("true") ? true : false;
                    classFullName = getFullClassName(iter.Current.GetAttribute("class", ""));
                    ///////////////////////////////////
                    strSqlSelect.Append(tableName);
                    strSqlSelect.Append(_WHERE);
                    //////////////////////////////////
                    strSqlInsert.Append(tableName + "(");
                    //////////////////////////////////
                    strSqlUpdate.Append(tableName);
                    strSqlUpdate.Append(_SET);
                    ///////////////////////////////////////
                    strSqlDelete.Append(tableName);
                    strSqlDelete.Append(_WHERE);

                }//end if
                if (iter.Current.HasChildren && iter.Current.MoveToFirstChild())
                {
                    StringBuilder insertValue = new StringBuilder(" values (");//insert value part
                    //first must primaryKey
                    string primaryKey = iter.Current.GetAttribute("name", "");
                    string primaryKeyValue = iter.Current.Value;
                    string updateWhere = _WHERE + "[" + primaryKey + "]";
                    strSqlSelect.Append("[" + primaryKey + "]");
                    strSqlDelete.Append("[" + primaryKey + "]");
                    if (!identity)
                        strSqlInsert.Append("[" + primaryKey + "],");
                    if (iter.Current.Value.Substring(0, 1).Equals("@"))//string
                    {
                        strSqlSelect.Append("='$" + primaryKeyValue + "$'");
                        strSqlDelete.Append("='$" + primaryKeyValue + "$'");
                        updateWhere += ("='$" + primaryKeyValue + "$'");
                        if (!identity)//if primary key isn't a identity id
                        {
                            insertValue.Append("'$" + primaryKeyValue + "$',");

                        }
                    }
                    else
                    {
                        strSqlSelect.Append("=$" + primaryKeyValue+"$");
                        strSqlDelete.Append("=$" + primaryKeyValue+"$");
                        updateWhere += ("=$" + primaryKeyValue+"$");
                        if (!identity)//if primary key isn't a identity id
                        {
                            insertValue.Append("$"+primaryKeyValue + "$,");
                        }
                    }
                    while (iter.Current.MoveToNext())
                    {
                        string name = iter.Current.GetAttribute("name", "");
                        string value = iter.Current.Value;
                        strSqlInsert.Append("[" + name + "],");
                        
                        if (value.Substring(0, 1).Equals("@"))//string
                        {

                            insertValue.Append("'$" + value + "$',");
                            strSqlUpdate.Append("[" + name + "]='$" + value + "$',");
                        }
                        else
                        {
                            insertValue.Append("$"+value + "$,");
                            strSqlUpdate.Append("[" + name + "]=$" + value + "$,");
                        }
                    }
                    insertValue.Remove(insertValue.Length - 1, 1).Append(")");
                    strSqlInsert.Remove(strSqlInsert.Length - 1, 1).Append(")" + insertValue.ToString()).Replace("#", "@");
                    strSqlUpdate.Remove(strSqlUpdate.Length - 1, 1).Append(updateWhere).Replace("#", "@");
                    strSqlSelect.Replace("#", "@");
                    strSqlDelete.Replace("#", "@");
                    Map curd = new Map();
                    curd.Create = strSqlInsert.ToString();
                    curd.Delete = strSqlDelete.ToString();
                    curd.Read = strSqlSelect.ToString();
                    curd.Update = strSqlUpdate.ToString();
                    _maps.Add(classFullName, curd);
                }//end if
            }  //end while          
        }
        private string getFullClassName(string str)
        {
            string[] tmp = str.Split(new char[] { ',' });
            if (tmp == null || tmp.Length != 2)
                return null;
            return tmp[0];//.Replace(tmp[1] + ".", "");
        }
        private string getAssemblyName(string str)
        {
            string[] tmp = str.Split(new char[] { ',' });
            if (tmp == null || tmp.Length != 2)
                return null;
            return tmp[1];
        }
    }
}
